﻿using System;
using CoreLibrary.Email.Impl.Mandrill;
using CoreLibrary.Service;

namespace CoreLibrary.Email.Impl {

    public class MandrillEmailService : ServiceBase, IEmailService{

        public int MaxRetries { get; set; }
        public IMandrillConfig Configuration { get; set; }

        public MandrillEmailService() {
            MaxRetries = 3;
        }

        protected override void OnInit() {
            Asserts.NotNull(Configuration,"Mandrill Configuration is required.");
        }

        protected override void OnStart() {
            GetOrCreateAPI();
        }

        protected override void OnStop()    {}
        protected override void OnDestroy() {}

        public SendEmailResponse SendEmail(SendEmailRequest request) {
            var builder = new MailBuilder();
            if (!string.IsNullOrEmpty(request.HtmlBody)) {
                 builder.SetHtmlBody(request.HtmlBody);
            }

            builder.SetSubject (Util.GetString(request.Subject));
            builder.SetTextBody(Util.GetString(request.TextBody));
            builder.SetSender  (Util.GetString(request.From.Name),request.From.Email);
            builder.SetReplyEmailAddress(Util.GetString(request.ReplyTo, request.From.Email));

            if (!CollectionUtil.IsEmpty(request.To)) {
                 request.To.ForEach(to => builder.AddRecipient(
                       new MailRecipient {
                           name  = Util.GetString(to.Name),
                           email = to.Email
                       }
                 ));
            }

            if (!CollectionUtil.IsEmpty(request.EmailAttachments)) {
                 request.EmailAttachments.ForEach(file => builder.AppendMailAttachment(
                     MailAttachment.Create(file.Name, file.Content)
                 ));
            }

            var mailMessage = builder.Build();

            Exception lastError = null;
            for (var attempts = 1; attempts <= MaxRetries; attempts++) {
                try {
                    var api = GetOrCreateAPI();
                    var mailResults = api.Send(mailMessage, DateTime.Now);
                    return SendEmailResponse.Create(mailResults);
                } 
                catch (Exception exception) {
                    if (attempts >= MaxRetries) {
                        lastError = exception;
                    }
                }
            }

            throw lastError != null ?
                  new SendEmailException(MaxRetries, lastError) :
                  new SendEmailException("can't deliver with " + MaxRetries + " attempts", MaxRetries);
        }

        private volatile MandrillAPI _emailApi;
        private MandrillAPI GetOrCreateAPI() {
            if (_emailApi == null) {
                lock (this) {
                    if (_emailApi == null) {
                        _emailApi = new MandrillAPI(Configuration);
                    }
                }
            }
            return _emailApi;
        }

        
    }

}